package com.qf.test.realm;

import com.qf.test.pojo.SysUsers;
import com.qf.test.servlet.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Set;

/**
 * 自定义Realm类
 * 1.获取数据库中的用户密码：根据用户名密码，到mysql数据库的用户表中查询数据库中的用户名密码
 * 交给SecurityManager
 * 2.授权:如果用户名密码正确  赋予用户 对应的角色和权限
 */
public class MyUserRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;

    /**
     * 授权方法：用户名密码校验成功后自定执行这个方法进行授权 赋予用户对应的角色和权限
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("自定义Realm=doGetAuthorizationInfo 方法授权 根据用户名权限授予对应的权限给这个用户 ");
        //1 获取认证的时候shiro框架中的session存储的用户对象
        SysUsers user = (SysUsers) principalCollection.getPrimaryPrincipal();
        int userId = user.getId();
        //2.根据用户id 到角色表中获取用户的角色信息
        Set<String> roleList = userService.findRolesByUid(userId);
        //3.根据用户id 到数据库权限表或者菜单中获取用户的权限信息
        Set<String> permList = userService.findPermByUid(userId);
        //4.封装shrio规定的角色权限对象
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
        //5.将角色数据赋予shrio对象
        authorizationInfo.setRoles(roleList);
        //6.将权限数据赋予hsiro的权限对象
        authorizationInfo.setStringPermissions(permList);
        ;
        //7.返回shiro的权限给 securityManager核心对象
        return authorizationInfo;

    }

    /**
     * 认证方法：从mysql中，根据用户名，获取user表中的用户对象，交割shriokuangjia de SevcuritManager核心管理
     *
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        System.out.println("自定义Realm,doGetAuthenticationInfo方法  进行登录认证 判断用户名密码是否正确");
        //1.获取用户在登录页面中输入的用户名

        String userName = (String) token.getPrincipal();

        //2.获取用户在当前输入的密码 shiro规定密码必须先转换成char类型的数组，然后在转换成String类型的字符串
        String password = new String((char[])token.getCredentials());

        //3.根据用户名到数据库查找用户对象
        SysUsers user = userService.findUsserByName(userName);
        //4.如果用户对象找不到 抛异常，用户不存在
        if (user == null) {
            throw new UnknownAccountException("用户不存在");
        }
        System.out.println(password);
        System.out.println(user.getPassword());
        //5.如果用户对象获取到 对比密码是否正确
        if (!password.equals(user.getPassword())) {
            //6.如果密码不对 抛异常
            throw new IncompatibleClassChangeError("密码不正确");
        }
        //7如果密码正确 封装返回的用户对象给shiro框架的Securitymanager核心
        //第一参数:用户对象  第二参数：密码  第三参数：当前 自定义realm对象的名称
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, this.getName());
        System.out.println("name"+this.getName());
        return info;


    }
}
